package com.sirui.jpa.dynamicquery;

import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;

/**
 * 动态jpql/nativeSql查询的实现类
 * 创建者
 * 创建时间	2018年3月8日
 */
@Repository
@Transactional(readOnly = true)
public class DynamicQueryImpl implements DynamicQuery {
    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

    @Override
    public void save(Object entity) {
        entityManager.persist(entity);
    }

    @Override
    public void update(Object entity) {
        entityManager.merge(entity);
    }

    @Override
    public <T> void delete(Class<T> entityClass, Object entityId) {
        delete(entityClass, new Object[]{entityId});
    }

    @Override
    public <T> void delete(Class<T> entityClass, Object[] entityIds) {
        for (Object id : entityIds) {
            entityManager.remove(entityManager.getReference(entityClass, id));
        }
    }

    private Query createNativeQuery(String sql, Object... params) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                nativeQuery.setParameter(i + 1, params[i]); // 与Hibernate不同,jpa query从位置1开始
            }
        }
        return nativeQuery;
    }

    @Override
    public <T> List<T> nativeQueryList(String nativeSql, Object... params) {
        Query nativeQuery = createNativeQuery(nativeSql, params);
        nativeQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.TO_LIST);
        return nativeQuery.getResultList();
    }

    @Override
    public <T> List<T> nativeQueryListModel(Class<T> resultClass, String nativeSql, Object... params) {
        Query nativeQuery = createNativeQuery(nativeSql, params);
        nativeQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(resultClass));
        return nativeQuery.getResultList();
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> List<T> nativeQueryListMap(String nativeSql, Object... params) {
        Query nativeQuery = createNativeQuery(nativeSql, params);
        nativeQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return nativeQuery.getResultList();
    }

}
